home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Mac / think / fopenRF.c
Text File  |  1995-08-07  |  6KB  |  337 lines

  1.  
  2. /*
  3.  *  fopen.c
  4.  *
  5.  *  Copyright (c) 1991 Symantec Corporation.  All rights reserved.
  6.  *
  7.  */
  8.  
  9. #include <MacHeaders>
  10.  
  11. #include "stdio.h"
  12. #include "errno.h"
  13. #include "string.h"
  14. #include "ansi_private.h"
  15.  
  16. extern long _ftype, _fcreator;
  17.  
  18. #define fcbVPtr(fcb)        (* (VCB **) (fcb + 20))
  19. #define fcbDirID(fcb)        (* (long *) (fcb + 58))
  20. #define fcbCName(fcb)        (fcb + 62)
  21.  
  22. static void setfiletype(StringPtr, int);
  23. static void stdio_exit(void);
  24. static int fileio(FILE *, int);
  25. static int close(FILE *);
  26. static void replace(unsigned char *, size_t, int, int);
  27.  
  28. FILE *freopenRF();
  29. FILE *__openRF();
  30.  
  31. FILE *
  32. fopenRF(const char *filename, const char *mode)
  33. {
  34.     return(freopenRF(filename, mode, __getfile()));
  35. }
  36.  
  37.  
  38. FILE *
  39. freopenRF(const char *filename, const char *mode, FILE *fp)
  40. {
  41.     int omode, oflag;
  42.     
  43.         /*  interpret "rwa"  */
  44.     
  45.     if (mode[0] == 'r') {
  46.         omode = fsRdPerm;
  47.         oflag = 0;
  48.     }
  49.     else if (mode[0] == 'w') {
  50.         omode = fsWrPerm;
  51.         oflag = F_CREAT+F_TRUNC;
  52.     }
  53.     else if (mode[0] == 'a') {
  54.         omode = fsWrPerm;
  55.         oflag = F_CREAT+F_APPEND;
  56.     }
  57.     else {
  58.         errno = EINVAL;
  59.         return(NULL);
  60.     }
  61.         
  62.         /*  interpret "b+"  */
  63.         
  64.     if (mode[1] == 'b') {
  65.         oflag |= F_BINARY;
  66.         if (mode[2] == '+')
  67.             omode = fsRdWrPerm;
  68.     }
  69.     else if (mode[1] == '+') {
  70.         omode = fsRdWrPerm;
  71.         if (mode[2] == 'b')
  72.             oflag |= F_BINARY;
  73.     }
  74.     
  75.         /*  open the file  */
  76.         
  77.     return(__openRF(filename, omode, oflag, fp));
  78. }
  79.  
  80.  
  81. FILE *
  82. __openRF(const char *filename, int omode, int oflag, FILE *fp)
  83. {
  84.     IOParam pb;
  85.     char pname[FILENAME_MAX];
  86.  
  87.     if (fp == NULL)
  88.         return(NULL);
  89.     fclose(fp);
  90.     
  91.         /*  set up pb  */
  92.     
  93.     pb.ioNamePtr = __c2p(filename, pname);
  94.     pb.ioVRefNum = 0;
  95.     pb.ioVersNum = 0;
  96.     pb.ioPermssn = omode;
  97.     pb.ioMisc = 0;
  98.  
  99.         /*  create file  */
  100.  
  101.     if (oflag & F_CREAT) {
  102.         PBCreateSync((ParmBlkPtr)&pb);
  103.         if (pb.ioResult == noErr)
  104.             oflag &= ~F_TRUNC;
  105.         else if (pb.ioResult == dupFNErr && !(oflag & F_EXCL))
  106.             oflag &= ~F_CREAT;
  107.         else {
  108.             errno = pb.ioResult;
  109.             return(NULL);
  110.         }
  111.     }
  112.     
  113.         /*  open file  */
  114.         
  115.     PBOpenRFSync((ParmBlkPtr)&pb);
  116.     if (pb.ioResult) {
  117.         errno = pb.ioResult;
  118.         if (oflag & F_CREAT)
  119.             PBDeleteSync((ParmBlkPtr)&pb);
  120.         return(NULL);
  121.     }
  122.     fp->refnum = pb.ioRefNum;
  123.     
  124.         /*  get/set file length  */
  125.         
  126.     if (oflag & F_TRUNC)
  127.         PBSetEOFSync((ParmBlkPtr)&pb);
  128.     else if (!(oflag & F_CREAT))
  129.         PBGetEOFSync((ParmBlkPtr)&pb);
  130.     fp->len = (fpos_t) pb.ioMisc;
  131.         
  132.         /*  initialize rest of FILE structure  */
  133.         
  134.     if (oflag & F_APPEND) {
  135.         fp->append = 1;
  136.         fp->pos = fp->len;
  137.     }
  138.     if (oflag & F_BINARY)
  139.         fp->binary = 1;
  140.     setvbuf(fp, NULL, _IOFBF, BUFSIZ);
  141.     fp->proc = fileio;
  142.  
  143.         /*  set file type  */
  144.  
  145.     if (oflag & (F_CREAT|F_TRUNC))
  146.         setfiletype(pb.ioNamePtr, oflag);
  147.         
  148.         /*  done  */
  149.         
  150.     __atexit_stdio(stdio_exit);
  151.     return(fp);
  152. }
  153.  
  154.  
  155. /*
  156.  *  setfiletype - set type/creator of new file
  157.  *
  158.  */
  159.  
  160. static void
  161. setfiletype(StringPtr name, int oflag)
  162. {
  163.     FileParam pb;
  164.     
  165.     pb.ioNamePtr = name;
  166.     pb.ioVRefNum = 0;
  167.     pb.ioFVersNum = 0;
  168.     pb.ioFDirIndex = 0;
  169.     if (PBGetFInfoSync((ParmBlkPtr)&pb) == noErr) {
  170.         if (oflag & F_BINARY)
  171.             pb.ioFlFndrInfo.fdType = _ftype;
  172.         else
  173.             pb.ioFlFndrInfo.fdType = 'TEXT';
  174.         pb.ioFlFndrInfo.fdCreator = _fcreator;
  175.         PBSetFInfoSync((ParmBlkPtr)&pb);
  176.     }
  177. }
  178.  
  179.  
  180. /*
  181.  *  stdio_exit - stdio shutdown routine
  182.  *
  183.  */
  184.  
  185. static void
  186. stdio_exit(void)
  187. {
  188.     register FILE *fp;
  189.     int n;
  190.     
  191.     for (fp = &__file[0], n = FOPEN_MAX; n--; fp++)
  192.         fclose(fp);
  193. }
  194.  
  195.  
  196. /*
  197.  *  fileio - I/O handler proc for files and devices
  198.  *
  199.  */
  200.  
  201. static int
  202. fileio(FILE *fp, int i)
  203. {
  204.     IOParam pb;
  205.     
  206.     pb.ioRefNum = fp->refnum;
  207.     switch (i) {
  208.     
  209.                 /*  read  */
  210.             
  211.         case 0:
  212.             pb.ioBuffer = (Ptr) fp->ptr;
  213.             pb.ioReqCount = fp->cnt;
  214.             pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
  215.             pb.ioPosOffset = fp->pos - fp->cnt;
  216.             PBReadSync((ParmBlkPtr)&pb);
  217.             if (pb.ioResult == eofErr) {
  218.                 fp->pos = pb.ioPosOffset;
  219.                 if (fp->cnt = pb.ioActCount)
  220.                     pb.ioResult = 0;
  221.                 else {
  222.                     fp->eof = 1;
  223.                     return(EOF);
  224.                 }
  225.             }
  226.             if (!pb.ioResult && !fp->binary)
  227.                 replace(fp->ptr, fp->cnt, '\r', '\n');
  228.             break;
  229.             
  230.                 /*  write  */
  231.  
  232.         case 1:
  233.             pb.ioBuffer = (Ptr) fp->ptr;
  234.             pb.ioReqCount = fp->cnt;
  235.             pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark;
  236.             if ((pb.ioPosOffset = fp->pos - fp->cnt) > fp->len) {
  237.                 pb.ioMisc = (Ptr) pb.ioPosOffset;
  238.                 if (PBSetEOFSync((ParmBlkPtr)&pb) != noErr)
  239.                     break;
  240.             }
  241.             if (!fp->binary)
  242.                 replace(fp->ptr, fp->cnt, '\n', '\r');
  243.             PBWriteSync((ParmBlkPtr)&pb);
  244.             if (!pb.ioResult && pb.ioPosOffset > fp->len)
  245.                 fp->len = pb.ioPosOffset;
  246.             break;
  247.             
  248.                 /*  close  */
  249.  
  250.         case 2:
  251.             pb.ioResult = close(fp);
  252.             break;
  253.     }
  254.     
  255.         /*  done  */
  256.         
  257.     if (pb.ioResult) {
  258.         if (i < 2) {
  259.             fp->pos -= fp->cnt;
  260.             fp->cnt = 0;
  261.         }
  262.         fp->err = 1;
  263.         errno = pb.ioResult;
  264.         return(EOF);
  265.     }
  266.     return(0);
  267. }
  268.  
  269.  
  270. static int
  271. close(FILE *fp)
  272. {
  273.     HFileParam pb;
  274.     Str255 buf;
  275.     register char *fcb = FCBSPtr + fp->refnum;
  276.     VCB *vcb = fcbVPtr(fcb);
  277.     register char *s;
  278.     enum { none, MFS, HFS } del = none;
  279.     
  280.     pb.ioVRefNum = vcb->vcbVRefNum;
  281.     if (fp->remove) {
  282.         pb.ioNamePtr = buf;
  283.         pb.ioFVersNum = 0;
  284.     
  285.             /*  close temporary file - HFS  */
  286.             
  287.         if (vcb->vcbSigWord == 0x4244) {
  288.             pb.ioDirID = fcbDirID(fcb);
  289.             s = fcbCName(fcb);
  290.             memcpy(buf, s, Length(s) + 1);
  291.             del = HFS;
  292.         }
  293.         
  294.             /*  close temporary file - MFS  */
  295.             
  296.         else if (vcb->vcbSigWord == 0xD2D7) {
  297.             for (pb.ioFDirIndex = 1; PBGetFInfoSync((ParmBlkPtr)&pb) == noErr; pb.ioFDirIndex++) {
  298.                 if (pb.ioFRefNum == fp->refnum) {
  299.                     del = MFS;
  300.                     break;
  301.                 }
  302.             }
  303.         }
  304.     }
  305.     
  306.         /*  close file and flush volume buffer  */
  307.     
  308.     pb.ioFRefNum = fp->refnum;
  309.     if (PBCloseSync((ParmBlkPtr)&pb) == noErr) {
  310.         if (del == MFS)
  311.             PBDeleteSync((ParmBlkPtr)&pb);
  312.         else if (del == HFS)
  313.             PBHDeleteSync((HParmBlkPtr)&pb);
  314.         pb.ioNamePtr = 0;
  315.         PBFlushVolSync((ParmBlkPtr)&pb);
  316.     }
  317.     return(pb.ioResult);
  318. }
  319.  
  320.  
  321. /*
  322.  *  replace - routine for doing CR/LF conversion
  323.  *
  324.  */
  325.  
  326. static void
  327. replace(register unsigned char *s, register size_t n, register int c1, register int c2)
  328. {
  329. #pragma options(honor_register)
  330.     register unsigned char *t;
  331.     
  332.     for (; n && (t = memchr(s, c1, n)); s = t) {
  333.         *t++ = c2;
  334.         n -= t - s;
  335.     }
  336. }
  337.